/*
 * sd.c
 *
 *  Created on: 2025年4月28日
 *      Author: Administrator
 */
#include "sd.h"
#include "MyFreertos.h"
#define DATA "2:/data"
#define NUM "2:/num"
#define RECORD_DATALENGTH 		512
#define RECORDFILEMAXSIZE 		RECORD_DATALENGTH * 5 * 3600 * 6
#define RECORDFILEMAXNUM 		101
DIR dir;
FIL sd_file_num;  /* File object */
FIL sd_file_record;  /* File object */
FATFS sd_fatfs; /* File system object */
FILINFO fno;
FRESULT fres;
uint8_t pattern[8];
uint8_t num_path[64];
uint8_t data_path[64];
uint32_t num;
uint32_t bytewrite=0,byteread=0;
uint64_t filesize;
/*! @brief SD card detect flag  */
static volatile bool s_cardInserted     = false;
static volatile bool s_cardInsertStatus = false;
/*! @brief Card semaphore  */
static SemaphoreHandle_t s_CardDetectSemaphore = NULL;
static void SDCARD_DetectCallBack(bool isInserted, void *userData)
{
    s_cardInsertStatus = isInserted;
    xSemaphoreGiveFromISR(s_CardDetectSemaphore, NULL);
}
void SdInit()
{
	s_CardDetectSemaphore = xSemaphoreCreateBinary();
	BOARD_SD_Config(&g_sd, SDCARD_DetectCallBack, BOARD_SDMMC_SD_HOST_IRQ_PRIORITY, NULL);
	/* SD host init function */
	if (SD_HostInit(&g_sd) == kStatus_Success)
	{
		while (true)
		{
			/* take card detect semaphore */
			if (xSemaphoreTake(s_CardDetectSemaphore, 1000) == pdTRUE)
			{
				if (s_cardInserted != s_cardInsertStatus)
				{
					s_cardInserted = s_cardInsertStatus;
					if (s_cardInserted)
					{
						PRINTF("\r\nCard inserted.\r\n");
						/* power off card */
						SD_SetCardPower(&g_sd, false);
						/* power on the card */
						SD_SetCardPower(&g_sd, true);
						/* make file system */
						if (DEMO_MakeFileSystem() != kStatus_Success)
						{
							continue;
						}
						return;
					}
				}
			}
			else
			{
				if (!s_cardInserted)
				{
//					taskENTER_CRITICAL();
//					PRINTF("\r\nPlease insert a card into board.\r\n");
//					taskEXIT_CRITICAL();
					vTaskDelay(1000);
				}
			}
		}
	}
	else
	{
		PRINTF("\r\nSD host init fail\r\n");
	}
}
status_t DEMO_MakeFileSystem(void)
{
	PRINTF("\r\nSD mount......\r\n");
    const TCHAR driverNumberBuffer[3U] = {SDDISK + '0', ':', '/'};
    BYTE work[FF_MAX_SS];
    fres=f_mount(&sd_fatfs, driverNumberBuffer, 0U);
    if(fres==FR_NO_FILESYSTEM)
    {
		PRINTF("\r\nMake file system......The time may be long if the card capacity is big.\r\n");
		if (f_mkfs(driverNumberBuffer, 0, work, sizeof work))
		{
			PRINTF("Make file system failed.\r\n");
			return kStatus_Fail;
		}
    }
    PRINTF("\r\nCreate directory......\r\n");
    fres = f_mkdir(NUM);
    fres = f_mkdir(DATA);
    sprintf(num_path,"%s/%s.bin",NUM,"number");
    fres=f_open(&sd_file_num, num_path, FA_READ|FA_WRITE|FA_OPEN_ALWAYS);
  	if(fres==FR_OK)
  	{
  		fres=f_read(&sd_file_num, &num, sizeof(num),&byteread);
  		f_lseek(&sd_file_num, 0);
  		if(num == 0 || num == RECORDFILEMAXNUM)
  			num=1;
  	}
  	sprintf(pattern,"%d_*",num);
	if (f_findfirst(&dir, &fno,DATA, pattern) == FR_OK)
	{
		sprintf(data_path,"%s/%s",DATA,fno.fname);
	}
	fres=f_open(&sd_file_record, data_path, FA_READ | FA_WRITE | FA_OPEN_EXISTING);
	if(fres == FR_OK)
	{
		f_close(&sd_file_record);
		fres=f_open(&sd_file_record, data_path, FA_WRITE|FA_OPEN_APPEND);
	}
	else
	{
		f_close(&sd_file_record);
		SNVS_LP_SRTC_GetDatetime(SNVS, &rtc_date_now);
		sprintf(data_path,"%s/%d_%04d%02d%02d%02d%02d%02d.bin",DATA,num,rtc_date_now.year,rtc_date_now.month,rtc_date_now.day,rtc_date_now.hour,rtc_date_now.minute,rtc_date_now.second);
		fres=f_open(&sd_file_record, data_path, FA_WRITE|FA_OPEN_APPEND);
	}
	fres=f_write(&sd_file_num, &num, sizeof(num), &bytewrite);
	f_sync(&sd_file_num);
	f_lseek(&sd_file_num, 0);
    return kStatus_Success;
}
void SdRecordLoop(uint8_t * record_data, uint32_t record_len)
{
	if(f_size(&sd_file_record) >= RECORDFILEMAXSIZE)
	{
		filesize = 0;
		f_close(&sd_file_record);
		num++;
		if(num == RECORDFILEMAXNUM)
		{
			num = 1;
		}
		sprintf(pattern,"%d_*",num);
		while (f_findfirst(&dir, &fno,DATA, pattern) == FR_OK)
		{
			if(fno.fname[0] == 0)
			{
				break;
			}
			sprintf(data_path,"%s/%s",DATA,fno.fname);
			fres=f_unlink(data_path);
		}
		sprintf(data_path,"%s/%d_%04d%02d%02d%02d%02d%02d.bin",DATA,num,rtc_date_now.year,rtc_date_now.month,rtc_date_now.day,rtc_date_now.hour,rtc_date_now.minute,rtc_date_now.second);
		fres=f_open(&sd_file_record,data_path, FA_WRITE|FA_OPEN_APPEND);
		f_write(&sd_file_num, &num, sizeof(num), &bytewrite);
		f_sync(&sd_file_num);
		f_lseek(&sd_file_num, 0);
	}
	fres=f_write(&sd_file_record, record_data, record_len, &bytewrite);
	if(fres==FR_OK)
	{
		f_sync(&sd_file_record);
		filesize += bytewrite;
	}
}
